package com.darwin.darwinNet
{
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import flash.utils.getTimer;

	/**
	 * C++通讯 协议解析器 
	 * @author vanCopper
	 * 
	 */	
	public class StructAnalyzer
	{
		public function StructAnalyzer()
		{
		}
		
		/**
		 * 将C++后台返回的字节碼解析为AS可用数据结构
		 *  
		 * @param byteArray
		 * @return 
		 * 
		 */		
		public function decode(byteArray:ByteArray,netStruct:INetStruct):Object
		{
//			var netStruct:INetStruct = Net.getInstance().netStruct;
			byteArray.endian = Endian.LITTLE_ENDIAN;
			var dataL:uint = byteArray.readUnsignedInt();
//			trace(dataL.toString(2));
			var isCompress:uint = dataL>>>30;
			var bodyByteArray:ByteArray = new ByteArray();
			byteArray.readBytes(bodyByteArray,0,byteArray.bytesAvailable);
			
			if(isCompress)
			{
				bodyByteArray.uncompress();
			}
			
			var byCmd:uint = bodyByteArray.readByte();
			var byParam:uint = bodyByteArray.readByte();
			var serverTime:uint = bodyByteArray.readUnsignedInt();
			//TODO 解析数据包
			var struct:Array = netStruct.getNetStruct(""+byCmd,""+byParam);
			var bodyObj:Object = decodeBody(bodyByteArray,struct);
			trace(dataL>>>31);
			return bodyObj;
		}
		
		private function decodeBody(bodyByteArray:ByteArray, struct:Array):Object
		{
			var returnObj:Object = {};
			bodyByteArray.endian = Endian.LITTLE_ENDIAN;
			for(var i:int = 0; i<struct.length; i++)
			{
				var key:String = struct[i][0];
				var type:int = struct[i][1];
				var length:int = struct[i][2];
				switch(type)
				{
					case 1://数字
						if(length == 32)
						{
							returnObj[key] = bodyByteArray.readUnsignedInt();
						}else if(length == 16)
						{
							returnObj[key] = bodyByteArray.readShort();
						}else if(length == 8)
						{
							returnObj[key] = bodyByteArray.readByte();
						}else if(length == 64)
						{
//							bodyByteArray.endian = Endian.LITTLE_ENDIAN;
							var long_b : int;
							var long_l : uint;
							long_b = bodyByteArray.readUnsignedInt();
							long_l  = bodyByteArray.readUnsignedInt();
							var Double:Number = Number (long_b) * (1<<32) +  long_l;
							returnObj[key] = bodyByteArray.readDouble();
						}
						break;
					case 2://字符串
						returnObj[key] = bodyByteArray.readUTFBytes(length);
						break;
					case 3://固定长度数组&Object
						returnObj[key] = decodeBody(bodyByteArray,struct[i][3]);
						break;
					case 4://Boolean
						returnObj[key] = bodyByteArray.readBoolean();
						break;
					case 5://不定长数组 数组元素必须是32位数字
						returnObj[key] = decodeVarrays(bodyByteArray);
						break;
				}
			}
			return returnObj;
		}
		
		private function decodeVarrays(byteArray:ByteArray):Array
		{
			var arrayLen:uint = byteArray.readUnsignedInt()/4;
			var returnArray:Array = [];
			for(var i:int = 0; i<arrayLen; i++)
			{
				var value:uint = byteArray.readUnsignedInt();
				returnArray.push(value);
			}
			return returnArray;
		}
		
		/**
		 * 将要发送的数据封装成ByteArray字节流 
		 * @param byCmd
		 * @param byParam
		 * @param time
		 * @param data
		 * @param struct
		 * @return 
		 * 
		 */		
		public function encode(byCmd:int,byParam:int,time:int,data:Object,struct:Array):ByteArray
		{
			var returnByteArray:ByteArray = new ByteArray();
			returnByteArray.endian = Endian.LITTLE_ENDIAN;
			
			var bodyByteArray:ByteArray = new ByteArray();
			bodyByteArray.endian = Endian.LITTLE_ENDIAN;
			bodyByteArray.writeByte(byCmd);
			bodyByteArray.writeByte(byParam);
			bodyByteArray.writeUnsignedInt(time);
			bodyByteArray.writeBytes(encodeBody(data,struct));
			var bodyLength:int = bodyByteArray.length;
			returnByteArray.writeUnsignedInt(bodyLength);
			
//			if(bodyLength > 12)
//			{
//				returnByteArray.writeUnsignedInt(bodyLength);
//				returnByteArray.writeUnsignedInt(bodyLength|0x80000000);
//				bodyByteArray.compress();
//			}else
//			{
//				returnByteArray.writeUnsignedInt(bodyLength);
//			}
			
			returnByteArray.writeBytes(bodyByteArray);
			returnByteArray.position = 0;
			
			return returnByteArray;
		}
		
		private function encodeBody(data:Object,struct:Array):ByteArray
		{
			var byteArray:ByteArray = new ByteArray();
			for(var i:int = 0; i<struct.length; i++)
			{
				var key:String = struct[i][0];
				var type:int = struct[i][1];
				var length:int = struct[i][2];
				switch(type)
				{
					case 1://数字
						if(length == 32)
						{
							byteArray.writeUnsignedInt(data[key]);
						}else if(length == 16)
						{
							byteArray.writeShort(data[key]);
						}else if(length == 8)
						{
							byteArray.writeByte(data[key]);
						}else if(length == 64)
						{
							byteArray.writeDouble(data[key]);
						}
					break;
					case 2://字符串
						byteArray.writeUTFBytes(data[key]);
						byteArray.writeByte(0);
//						byteArray.writeByte(1);
					break;
					case 3://固定长度数组 &Object
						byteArray.writeBytes(encodeBody(data[key],struct[i][3]));
					break;
					case 4://Boolean
						byteArray.writeBoolean(data[key]);
					break;
					case 5://不固定长度数组 数组元素必须是32位数字
						//TODO 编码长度不固定的数组
						byteArray.writeBytes(encodeVarrays(data[key]));
					break;
				}
			}
//			byteArray.endian = Endian.LITTLE_ENDIAN;
			return byteArray;
		}
		
		private function encodeVarrays(array:Array):ByteArray
		{
			var dataByteArray:ByteArray = new ByteArray();
			for(var i:int = 0; i<array.length; i++)
			{
				var value:int = array[i];
				dataByteArray.writeUnsignedInt(value);
			}
			var dataLen:uint = dataByteArray.length;
			var byteArray:ByteArray = new ByteArray();
			byteArray.writeUnsignedInt(dataLen);
			byteArray.writeBytes(dataByteArray);
			return byteArray;
		}
	}
}